package com.yj.web.util;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Created by yanlinyang on 2017/9/11.
 */
public class WxMessageInMemoryDuplicateChecker implements WxMessageDuplicateChecker {
    private final Long timeToLive;
    private final Long clearPeriod;
    private final ConcurrentHashMap<String, Long> msgId2Timestamp = new ConcurrentHashMap<String, Long>();
    private final AtomicBoolean backgroundProcessStarted = new AtomicBoolean(false);
    public WxMessageInMemoryDuplicateChecker() {
        this.timeToLive = 15 * 1000l;
        this.clearPeriod = 5 * 1000l;
    }
    public WxMessageInMemoryDuplicateChecker(Long timeToLive, Long clearPeriod) {
        this.timeToLive = timeToLive;
        this.clearPeriod = clearPeriod;
    }
    protected void checkBackgroundProcessStarted() {
        if (backgroundProcessStarted.getAndSet(true)) {
            return;
        }
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    while (true) {
                        Thread.sleep(clearPeriod);
                        Long now = System.currentTimeMillis();
                        for (Map.Entry<String, Long> entry : msgId2Timestamp.entrySet()) {
                            if (now - entry.getValue() > timeToLive) {
                                msgId2Timestamp.entrySet().remove(entry);
                            }
                        }
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t.setDaemon(true);
        t.start();
    }

    @Override
    public boolean isDuplicate(String messageId) {
        if (messageId == null) {
            return false;
        }
        checkBackgroundProcessStarted();
        Long timestamp = msgId2Timestamp.putIfAbsent(messageId, System.currentTimeMillis());
        if (timestamp == null) {
            // 第一次接收到这个消息
            return false;
        }
        return true;
    }
}
